package com.heima.comment.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import com.heima.aliyun.GreenTextScan;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.feigns.user.UserFeign;
import com.heima.model.Utils.threadlocal.AppThreadLocalUtils;
import com.heima.model.comment.dto.CommentDto;
import com.heima.model.comment.dto.CommentLikeDto;
import com.heima.model.comment.dto.CommentSaveDto;
import com.heima.model.comment.pojo.ApComment;
import com.heima.model.comment.pojo.ApCommentLike;
import com.heima.model.comment.vo.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojo.ApUser;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by ZYJ on 2021/6/5 20:35
 */
@Service
public class CommentServiceImpl implements CommentService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private UserFeign userFeign;
    @Autowired
    private GreenTextScan greenTextScan;

    /**
     * 发表评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //入参已注解校验
        ApUser user = AppThreadLocalUtils.getUser();
        //判断是否登录
        if (user == null || user.getId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //安全过滤
        boolean flag = handleTextScan(dto.getContent());
        if (!flag) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "评论审核未通过,请文明交流QWQ");
        }
        ApUser apUser = userFeign.findUserById(user.getId().longValue());
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE, "当前登录信息有误");
        }
        ApComment apComment = new ApComment();
        apComment.setAuthorId(apUser.getId());//此评论的作者,就是当前用户
        apComment.setAuthorName(apUser.getName());
        apComment.setEntryId(dto.getArticleId());
        apComment.setType((short) 0);
        apComment.setContent(dto.getContent());
        apComment.setImage(apUser.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag((short) 0);
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        this.mongoTemplate.insert(apComment);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Resource(name = "likesLock")
    RLock rLock;
    @Autowired
    CommentHotService commentHotService;

    /**
     * 点赞某文章下的某评论
     * 点赞与取消点赞
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDto dto) {
        //判断用户登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        rLock.lock();
        ApComment comment;
        try {
            //查询评论
            comment = this.mongoTemplate.findById(dto.getCommentId(), ApComment.class);
            if (comment == null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "哎呀这个评论突然找不到了");
            }
            //用户不能重复点赞
            ApCommentLike apCommentLike = this.mongoTemplate.findOne(Query.query(
                    Criteria.where("authorId").is(user.getId())
                            .and("commentId").is(dto.getCommentId()))
                    , ApCommentLike.class);
            if (apCommentLike != null && dto.getOperation() == 0) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "已经点过赞啦,请勿重复点赞");
            }
            if (dto.getOperation() == 0) {
                // 先把此评论点赞数+1
                comment.setLikes(comment.getLikes() + 1);
                mongoTemplate.save(comment);
                //点赞(保存点赞评论信息)
                apCommentLike = new ApCommentLike();
                apCommentLike.setAuthorId(user.getId());//点赞用户id
                apCommentLike.setCommentId(dto.getCommentId());
                apCommentLike.setOperation((short) 0);
                this.mongoTemplate.save(apCommentLike);
                //异步调用计算热点评论方法
                if (comment.getLikes() >= 5 && comment.getFlag().intValue() == 0) {
                    commentHotService.hotCommentExecutor(comment.getEntryId(), comment);
                }
            } else {
                //取消点赞
                // 先把此评论点赞数-1
                comment.setLikes(comment.getLikes() <= 0 ? 0 : comment.getLikes() - 1);
                this.mongoTemplate.save(comment);
                //删除点赞评论信息
                mongoTemplate.remove(Query.query(Criteria.
                        where("authorId").is(user.getId())
                        .and("commentId").is(comment.getId())), ApCommentLike.class);
            }
        } finally {
            rLock.unlock();
        }
        //4 数据返回 最新的点赞数
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("likes", comment.getLikes());

        return ResponseResult.okResult(resultMap);
    }

    /**
     * 根据文章id查询评论列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findByArticleId(CommentDto dto) {
        //入参注解已校验
        Integer size = dto.getSize();
        if (size == null || size <= 0) {
            dto.setSize(10); //给出默认
        }

        List<ApComment> apCommentList = null;
        //是1代表查询首页  不是1代表查询更多
        if (dto.getIndex().intValue() == 1) {
            //先查询热点评论
            Query hotQuery = Query.query(
                    Criteria.where("entryId").is(dto.getArticleId()) //文章id=?
                            .and("createdTime").lt(dto.getMinDate())//往下翻页就查询比前端传来的时间还要早的
                            .and("flag").is(1)) //热点评论
                    .with(Sort.by(Sort.Direction.DESC, "createdTime"));//按照时间倒序
            apCommentList = this.mongoTemplate.find(hotQuery, ApComment.class);
            if (apCommentList != null && apCommentList.size() > 0) {
                List<ApComment> normalList = getNormalComments(dto, dto.getSize() - apCommentList.size());
                apCommentList.addAll(normalList);
            } else {
                apCommentList = getNormalComments(dto, dto.getSize());
            }

        } else {

            apCommentList = getNormalComments(dto, dto.getSize());

        }


        //封装查询结果
        //用户未登录 ,直接返回
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null || CollUtil.isEmpty(apCommentList)) {
            return ResponseResult.okResult(apCommentList);
        }
        //用户登录，需要加载当前用户对评论点赞的列表
        List<ApCommentVo> apCommentVoList = new ArrayList<>();
        // 获取文章对应的所有评论ID列表
        List<String> idList = apCommentList.stream()
                .map(ApComment::getId)
                .collect(Collectors.toList());
        // 查询 在当前分页数据下 登录用户 所点赞过的所有数据
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(Query.query(
                Criteria.where("commentId").in(idList)
                        .and("authorId").is(user.getId())), ApCommentLike.class);
        //用户点过赞的评论id集合
        List<String> likeCommonIds = apCommentLikes.stream().map(ApCommentLike::getCommentId).collect(Collectors.toList());

        apCommentList.forEach(apComment -> {
            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtil.copyProperties(apComment, apCommentVo);
            //把点过赞的评论operation设置为0用于前端展示已点赞的
            if (likeCommonIds.contains(apComment.getId())) {
                apCommentVo.setOperation((short) 0);
            }
            apCommentVoList.add(apCommentVo);
        });
        return ResponseResult.okResult(apCommentVoList);
    }


    private List<ApComment> getNormalComments(CommentDto dto, Integer size) {
        Query query = Query.query(
                Criteria.where("entryId").is(dto.getArticleId()) //文章id=?
                        .and("createdTime").lt(dto.getMinDate())//往下翻页就查询比前端传来的时间还要早的
                        .and("flag").is(0)) //非热点评论
                .with(Sort.by(Sort.Direction.DESC, "createdTime"))//按照时间倒序
                .limit(size);
        return mongoTemplate.find(query, ApComment.class);
    }

    /**
     * 阿里云文本审核
     *
     * @param context
     * @return
     */
    private boolean handleTextScan(String context) {
        Boolean flag = true;
        try {
            Map map = greenTextScan.greenTextScan(context);
            String suggestion = (String) map.get("suggestion");
            if ("block".equals(suggestion)) {
                flag = false;
            }

        } catch (Exception e) {
            e.printStackTrace();
            flag = false;
        }
        return flag;
    }
}
